package great.project.common.utils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * 反射工具类
 *
 * @author Administrator
 */
public class ReflexUtils {

    private static final String GET_METHOD_PREFIX = "get";



    /**
     * 获取 指定类型的 所有的字段和对应的字段值
     *
     * @param clazz 指定的类型
     * @return 字段和对应的字段值
     */
    public static  <T> Map<String, Object> getClazzFieldAndValue(Class<? extends T> clazz, T t ) {
        return getClazzFieldAndValue(clazz , t , true);
    }


    /**
     * 获取 指定类型的 所有的字段和对应的字段值
     *
     * @param clazz 指定的类型
     * @param isSkipNull 是否跳过null值的字段
     * @return 字段和对应的字段值
     */
    public static  <T> Map<String, Object> getClazzFieldAndValue(Class<? extends T> clazz, T t , boolean isSkipNull) {

        Map<String, Object> map = new LinkedHashMap<>();

        // 该类的字段的所有的字段的名字
        List<String> fieldNameLists = new ArrayList<>();
        for (Field declaredField : clazz.getDeclaredFields()) {
            fieldNameLists.add(declaredField.getName());
        }

        for (Method declaredMethod : clazz.getDeclaredMethods()) {
            // 获取方法的名字
            String name = declaredMethod.getName();
            // 是否是 get开头的方法
            if (name.startsWith(GET_METHOD_PREFIX)) {
                try {
                    String fieldName = getFieldNameByGetMethod(name);
                    Object invoke = declaredMethod.invoke(t);

                    // 如果没有数据则跳过
                    if (isSkipNull && invoke==null) {
                        continue;
                    }
                    // 防止有get开头的方法，没有字段
                    if (fieldNameLists.contains(fieldName)) {
                        map.put(fieldName, invoke);
                    }
                } catch (IllegalAccessException | InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }
        return map;
    }


    /**
     * get方法的方法名字上获取字段的名字
     *  思路：getMethod ， 先移除 get 然后将剩余的首字母变小写 即可： 获取到 method。
     * @param methodName 方法的名字
     * @return 提取的字段的名字
     */
    public static String getFieldNameByGetMethod(String methodName) {
        String gets = methodName.replaceFirst(GET_METHOD_PREFIX, "");
        String s1 = String.valueOf(gets.charAt(0)).toLowerCase();
        char[] chars = gets.toCharArray();
        chars[0] = s1.charAt(0);
        return String.valueOf(chars);
    }

}
